package com.m.job.socket;

import java.io.IOException;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.m.job.server.service.MJobRegisterService;
import com.m.utils.SpringUtil;

import lombok.extern.slf4j.Slf4j;

/**
 * WebSocket服务入口
 *
 * @author monxz
 * @date 2019-03-12 15:16
 */
@Slf4j
@Component
@ServerEndpoint(value = "/mjob/register/{serverId}")
public class WebSocketClient {

	// 用来存储当前在线的客户端(此map线程安全)
	public  static ConcurrentHashMap<String, Session> webSocketMap = new ConcurrentHashMap<>();

	@Autowired
	private MJobRegisterService mJobRegisterService;

	/**
	 * 连接建立成功后调用
	 * 
	 * @throws Exception
	 */
	@OnOpen
	public void onOpen(@PathParam(value = "serverId") String serverId, Session session) {
		webSocketMap.put(serverId, session); // 加入map中
		log.info("客户端" + serverId + "加入，当前在线数为：" + getOnlineCount());

		if (mJobRegisterService == null) {
			mJobRegisterService = SpringUtil.getBean(MJobRegisterService.class);
		}
	}

	/**
	 * 连接关闭时调用
	 */
	@SuppressWarnings("unlikely-arg-type")
	@OnClose
	public void onClose() {
		webSocketMap.remove(this);
		log.info("有一连接关闭，当前在线数为：" + getOnlineCount());
	}

	/**
	 * 收到客户端消息后调用
	 *
	 * @param message 客户端发送过来的消息<br/>
	 *                消息格式：内容 - 表示群发，内容|X - 表示发给id为X的客户端
	 * @param session
	 * @throws IOException 
	 */
	
	@OnMessage
	public void onMessage(String message, Session session) throws IOException {		
		// 业务处理
		try {
			mJobRegisterService.dealClientDataJSon(message);
		} catch (Exception e1) {
			e1.printStackTrace();
			return;
		}		
	}

	/**
	 * 发生错误时回调
	 *
	 * @param session
	 * @param error
	 * @throws Exception 
	 */
	
	@OnError
	public void onError(Session session, Throwable error) throws Exception {
		String serverId = null;
		for(Entry<String, Session>  e : webSocketMap.entrySet()) {
			if(session.getId() .equals(e.getValue().getId())) {
				webSocketMap.remove(e.getKey());
				serverId = e.getKey();
				break ;
			}
		}
		if(serverId == null) {
			log.error("未知服务下线");
			return ;
		}
		mJobRegisterService.serverDown(serverId);
	}

	/**
	 * 推送信息给指定ID客户端，如客户端不在线，则返回不在线信息给自己
	 *
	 * @param message      客户端发来的消息
	 * @param sendClientId 客户端ID
	 * @throws IOException
	 */
	public void sendToUser(String message, String sendClientId) throws IOException {
		Session model = webSocketMap.get(sendClientId);
		if(model != null) {
			sendMessage(message, model);
		}
		
	}

	/**
	 * 推送发送信息给所有人
	 *
	 * @param message 要推送的消息
	 * @throws IOException
	 */
	public void sendToAll(String message) throws IOException {
		for (String key : webSocketMap.keySet()) {
			sendMessage(message, webSocketMap.get(key));
		}
	}

	public void sendToSome(String msg, String userNams) throws IOException {
		for (String id : userNams.split(",")) {
			sendMessage(msg, webSocketMap.get(id));
		}
	}

	/**
	 * 推送消息
	 *
	 * @param message 要推送的消息
	 * @throws IOException
	 */
	private void sendMessage(String message, Session session) throws IOException {
		session.getBasicRemote().sendText(message);
	}

	private static synchronized int getOnlineCount() {
		return webSocketMap.keySet().size();
	}

}
